import json
import os
import shutil
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
from threading import Timer


class SyncHandler(FileSystemEventHandler):
    def __init__(self, source, destination,delay=2):
        self.source = source
        self.destination = destination
        self.delay = delay
        self.timer = None

    def on_modified(self, event):
        if self.timer:
            self.timer.cancel()
        self.timer = Timer(self.delay, self.sync_files)
        self.timer.start()

    def on_created(self, event):
        if self.timer:
            self.timer.cancel()
        self.timer = Timer(self.delay, self.sync_files)
        self.timer.start()

    def on_deleted(self, event):
        if self.timer:
            self.timer.cancel()
        self.timer = Timer(self.delay, self.sync_files)
        self.timer.start()

    def sync_files(self):
        # Sync source to destination
        for root, dirs, files in os.walk(self.source):
            rel_path = os.path.relpath(root, self.source)
            dest_path = os.path.join(self.destination, rel_path)
            if not os.path.exists(dest_path):
                os.makedirs(dest_path)

            for file in files:
                src_file = os.path.join(root, file)
                dest_file = os.path.join(dest_path, file)
                try:
                    if not os.path.exists(dest_file) or os.stat(src_file).st_mtime > os.stat(dest_file).st_mtime:       
                        shutil.copy2(src_file, dest_file)
                except Exception as e:
                    print(f"An error occurred: {e}")

        # Clean up files not in source
        for root, dirs, files in os.walk(self.destination):
            rel_path = os.path.relpath(root, self.destination)
            src_path = os.path.join(self.source, rel_path)
            if not os.path.exists(src_path):
                shutil.rmtree(root)
                continue

            for file in files:
                dest_file = os.path.join(root, file)
                src_file = os.path.join(src_path, file)
                if not os.path.exists(src_file):
                    os.remove(dest_file)


def load_config(config_path):
    with open(config_path, "r") as f:
        return json.load(f)


def main():
    config = load_config("config.json")
    observers = []

    for dir_config in config["directories"]:
        source = dir_config["source"]
        destination = dir_config["destination"]

        event_handler = SyncHandler(source, destination)
        observer = Observer()
        observer.schedule(event_handler, path=source, recursive=True)
        observer.start()
        observers.append(observer)

    print("Watching directories for changes...")
    try:
        while True:
            pass
    except KeyboardInterrupt:
        for observer in observers:
            observer.stop()
        for observer in observers:
            observer.join()


if __name__ == "__main__":
    main()